package com.smdp.controller;


import com.smdp.dto.ChangePasswordFormDTO;
import com.smdp.dto.LoginFormDTO;
import com.smdp.dto.Result;
import com.smdp.dto.UserDTO;
import com.smdp.service.IUserService;
import com.smdp.utils.UserHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

/**
 * 用户功能前端控制器。
 * 包含发送（登录和修改密码的）验证码、登录（使用验证码或密码）、修改密码（使用验证码或密码）、查询“我的信息”、登出、根据用户id查询用户、签到
 * 以及查询连续签到天数。其中，发送验证码通过阿里云短信服务实现，验证码保存在Redis中；数据库只储存加盐加密的密码，防止用户密码泄露；
 * 根据id查询用户信息仅返回不敏感的信息，防止用户敏感信息泄露。
 *
 * @author 蔡方珩
 */
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {

    @Resource
    private IUserService userService;

    /**
     * 发送登录的手机验证码。
     * 通过阿里云服务实现短信发送，并将验证码保存在Redis中等待比对。
     * @param phone 电话号码
     * @return 成功：ok / 失败：失败原因
     */
    @PostMapping("/login/code")
    public Result sendCodeForLogin(@RequestParam("phone") String phone) {
        return userService.sendCodeForLogin(phone);
    }

    /**
     * 使用验证码用户登录。
     * 将用户提供的验证码与Redis中的验证码比对。
     * @param loginForm 登录表单，包含用户手机和验证码
     * @return 登录成功：token / 登录失败：失败原因
     */
    @PostMapping("/login/by/code")
    public Result loginByCode(@RequestBody LoginFormDTO loginForm){
        return userService.loginByCode(loginForm);
    }

    /**
     * 使用密码登录。
     * 将用户提供的密码加盐加密，并与数据库中的密码进行比对。
     * @param loginForm 登录表单，包含用户手机和密码
     * @return 登录成功：token / 登录失败：失败原因
     */
    @PostMapping("/login/by/password")
    public Result loginByPassword(@RequestBody LoginFormDTO loginForm){
        return userService.loginByPassword(loginForm);
    }

    /**
     * 通过旧密码修改密码。
     * 通过验证后将加盐加密的密码加入数据库。修改成功后登出。
     * @param changePasswordForm 修改密码表单
     * @param request http请求
     * @return 登录成功：ok / 登录失败：失败原因
     */
    @PostMapping("/change/password/by/password")
    public Result changePasswordByOldPassword(@RequestBody ChangePasswordFormDTO changePasswordForm, HttpServletRequest request){
        return userService.changePasswordByOldPassword(changePasswordForm, request);
    }

    /**
     * 发送修改密码的手机验证码
     * 通过阿里云服务实现，并将验证码保存在session中等待比对。
     * @param phone 电话号码
     * @return 成功：ok / 失败：失败原因
     */
    @PostMapping("/change/password/code")
    public Result sendCodeForChangePassword(@RequestParam("phone") String phone) {
        return userService.sendCodeForChangePassword(phone);
    }

    /**
     * 通过验证码修改密码。
     * 通过验证后将加盐加密的密码加入数据库。修改成功后登出。
     * @param changePasswordForm 修改密码表单
     * @param request http请求
     * @return 登录成功：ok / 登录失败：失败原因
     */
    @PostMapping("/change/password/by/code")
    public Result changePasswordByCode(@RequestBody ChangePasswordFormDTO changePasswordForm, HttpServletRequest request){
        return userService.changePasswordByCode(changePasswordForm, request);
    }

    /**
     * 登出
     * @param request http请求
     * @return ok
     */
    @PostMapping("/logout")
    public Result logout(HttpServletRequest request){
        return userService.logout(request);
    }

    /**
     * 获取用户的信息
     * @return user
     */
    @GetMapping("/me")
    public Result me(){
        UserDTO user = UserHolder.getUser();
        return Result.ok(user);
    }

    /**
     * 根据id查询用户信息。
     * @param userId 用户id
     * @return 成功：脱敏的用户信息 / 失败：ok
     */
    @GetMapping("/{id}")
    public Result queryUserById(@PathVariable("id") Long userId){
        return userService.queryUserById(userId);
    }

    /**
     * 用户签到。
     * 使用Redis的BitMap储存签到信息。
     * @return ok
     */
    @PostMapping("/sign")
    public Result sign(){
        return userService.sign();
    }

    /**
     * 统计用户连续签到天数。
     * 从BitMap中获取信息后统计天数。
     * @return 连续签到天数
     */
    @GetMapping("/sign/count")
    public Result signCount(){
        return userService.signCount();
    }


}
